package controleurType;

import grammaire.YakaConstants;

import java.util.HashMap;
import java.util.Stack;

/**
 * Controle les types de toutes les opérations du code
 * TEST:OK
 */
public class ControleurType implements Constantes,YakaConstants {

	public int [][][] tabControleTypeBinaire; 
	//matrice 3 dimensions permettant de g�rer le contr�le des types pour les op�rations binaires
	public int [][] tabControleTypeUnaire; 
	//matrice 2 dimensions permettant de g�rer le contr�le des types pour les op�rations unaires
	private HashMap<Integer, Integer> mapAssociation;
	//table d'association entre un op�rateur et sa classe 
	
	private Stack<Integer> pileOperateur;
	private Stack<Integer> pileOperande;

	/**
	 * Constructeur de contr�leur de types
	 * Initialise les attributs
	 */
	
	public ControleurType() {
		//cr�ation de la matrice controle de type op�rateurs binaires
		tabControleTypeBinaire = new int [NBOPERATEURSBINAIRES][NBOPERANDES][NBOPERANDES];
		//initialisation en dur de la matrice
		tabControleTypeBinaire[OPENTIER][ENTIERTYPE][ENTIERTYPE]=ENTIERTYPE;
		tabControleTypeBinaire[OPENTIER][ENTIERTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPENTIER][ENTIERTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPENTIER][BOOLEENTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPENTIER][BOOLEENTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPENTIER][BOOLEENTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPENTIER][ERREURTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPENTIER][ERREURTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPENTIER][ERREURTYPE][ERREURTYPE]=ERREURTYPE;
		
		
		tabControleTypeBinaire[OPDIFF][ENTIERTYPE][ENTIERTYPE]=BOOLEENTYPE;
		tabControleTypeBinaire[OPDIFF][ENTIERTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPDIFF][ENTIERTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPDIFF][BOOLEENTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPDIFF][BOOLEENTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPDIFF][BOOLEENTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPDIFF][ERREURTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPDIFF][ERREURTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPDIFF][ERREURTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPEGALITE][ENTIERTYPE][ENTIERTYPE]=BOOLEENTYPE;
		tabControleTypeBinaire[OPEGALITE][ENTIERTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPEGALITE][ENTIERTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPEGALITE][BOOLEENTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPEGALITE][BOOLEENTYPE][BOOLEENTYPE]=BOOLEENTYPE;
		tabControleTypeBinaire[OPEGALITE][BOOLEENTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPEGALITE][ERREURTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPEGALITE][ERREURTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPEGALITE][ERREURTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPBOOL][ENTIERTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPBOOL][ENTIERTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPBOOL][ENTIERTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPBOOL][BOOLEENTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPBOOL][BOOLEENTYPE][BOOLEENTYPE]=BOOLEENTYPE;
		tabControleTypeBinaire[OPBOOL][BOOLEENTYPE][ERREURTYPE]=ERREURTYPE;
		
		tabControleTypeBinaire[OPBOOL][ERREURTYPE][ENTIERTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPBOOL][ERREURTYPE][BOOLEENTYPE]=ERREURTYPE;
		tabControleTypeBinaire[OPBOOL][ERREURTYPE][ERREURTYPE]=ERREURTYPE;
		
		//cr�ation de la matrice controle de type op�rateurs unaires
		tabControleTypeUnaire = new int [NBOPERATEURSUNAIRES][NBOPERANDES];
		//initialisation en dur de la matrice
		tabControleTypeUnaire[OPNON][ENTIERTYPE] = ERREURTYPE;
		tabControleTypeUnaire[OPNON][BOOLEENTYPE] = BOOLEENTYPE;
		tabControleTypeUnaire[OPNON][ERREURTYPE] = ERREURTYPE;
		tabControleTypeUnaire[OPMOINS][ENTIERTYPE] = ENTIERTYPE;
		tabControleTypeUnaire[OPMOINS][BOOLEENTYPE] = ERREURTYPE;
		tabControleTypeUnaire[OPMOINS][ERREURTYPE] = ERREURTYPE;

		
		//cr�ation de la table d'association operateurs --> classe
		this.mapAssociation = new HashMap<Integer, Integer>();
		//initialisation en dur de la table d'association
		this.mapAssociation.put(PLUS,OPENTIER);
		this.mapAssociation.put(MOINS,OPENTIER);
		this.mapAssociation.put(MULT,OPENTIER);
		this.mapAssociation.put(DIV,OPENTIER);
		
		this.mapAssociation.put(INF,OPDIFF);
		this.mapAssociation.put(SUP,OPDIFF);
		this.mapAssociation.put(INFEQ,OPDIFF);
		this.mapAssociation.put(SUPEQ,OPDIFF);
		
		this.mapAssociation.put(EQ,OPEGALITE);
		this.mapAssociation.put(DIFF,OPEGALITE);
		
		this.mapAssociation.put(ET,OPBOOL);
		this.mapAssociation.put(OU,OPBOOL);
		
		//initialisation des piles
		pileOperateur= new Stack<Integer>();
		pileOperande= new Stack<Integer>();
	}
	
	
	/**
	 * M�thode d'association entre un op�rateur et sa classe
	 * @param operateur : l'op�rateur dont la classe est � determiner
	 * @return le num�ro de la classe de l'op�rateur
	 */
	public int associeOperateur (int operateur){
		return this.mapAssociation.get(operateur);
	}
	
	/**
	 * Red�finition de la m�thode toString
	 *  
	 */
	public String toString(){
		String s = "";
		for (int i = 0; i< NBOPERATEURSBINAIRES;i++){
			for (int j = 0; j < NBOPERANDES ; j++){
				for (int k = 0; k< NBOPERANDES; k++){
					s += this.tabControleTypeBinaire[i][j][k];
				}
				s+="\n";
			}
			s+="\n\n";
		}
		return s;
	}
	
	/**
	 * empile l'operateur dans la pile Operateur
	 */
	public void empileOperateur(int operateur){
		pileOperateur.push(operateur);
	}
	
	/**
	 * empile l'operande dans la pile Operande
	 */
	public void empileOperande(int operande){
		pileOperande.push(operande);
	}
	
	/**
	 * empile le type r�sultat de l'op�ration binaire
	 * issue du sommet de pile de la pile op�rateur 
	 * et des deux op�randes de la pile op�rande 
	 * void
	 */
	public void controleTypeBinaire(){
		int operateur=associeOperateur(pileOperateur.pop());
		int operande2=pileOperande.pop();
		int operande1=pileOperande.pop();
		pileOperande.push(tabControleTypeBinaire[operateur][operande1][operande2]);
		//System.out.println("RESULTAT BINAIRE: "+pileOperande.peek());
	}
	
	
	/**
	 * empile le type r�sultat unaire 
	 * issue du sommet de pile de la pile op�rateur 
	 * et du sommet de la pile op�rande 
	 * void
	 */
	public void controleTypeUnaire(){
		int operateur=pileOperateur.pop();
		int operande1=pileOperande.pop();
		pileOperande.push(tabControleTypeUnaire[operateur][operande1]);
		//System.out.println("RESULTAT UNAIRE: operateur"+operateur+"operande "+operande1+" : "+pileOperande.peek());
	}
}
